#include <iostream>
using std::cout;
using std::endl;
using std::cerr;

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>

// unsigned short sem_num;  /* semaphore number */
// short          sem_op;   /* semaphore operation */
// short          sem_flg;  /* operation flags */
 
union semun{
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };
 
void getkey(int semid)//得到钥匙
{
    struct sembuf sop;
    sop.sem_num = 0;//控制第一个信号量
    sop.sem_op  = -1;//钥匙数量减一6
    sop.sem_flg = SEM_UNDO;
    semop(semid,&sop,1);
}
 
void backkey(int semid)//放回钥匙
{
    struct sembuf sop;
    sop.sem_num = 0;
    sop.sem_op  = 1;
    sop.sem_flg = SEM_UNDO;
    semop(semid,&sop,1);
}

int main()
{
    key_t key = ftok(".",1);
    int semid = semget(key,1,IPC_CREAT| IPC_EXCL |0666);//创建信号量
    if(semid == -1)
    {
         cerr << "smeget error!"<<endl;
         exit(EOF);
    }
    union semun set; //设置控制信号量的结构体-联合体set
    set.val = 1;//钥匙数量为1 (资源数量为1)
    semctl(semid,0,SETVAL,set); //对信号量进行控制，第0个信号量，SETVAL将初始化信号量为一个已知的值，set为联合共用体，设置初始钥匙数量
   
    pid_t pid = fork();
    if(pid==0)
    {
        int i = 5;
        while(i--)
        {
             getkey(semid);//父进程获得钥匙，执行下面内容
             cout<<"this is child!\n"<<endl;//
             sleep(1);
             backkey(semid);//子进程放回钥匙
        }
        exit(1);
    }

    //父进程没有钥匙是无法运行的，阻塞状态。只能等待子进程放回钥匙
    while(waitpid(pid,NULL,WNOHANG) != pid)
    {
         getkey(semid);//父进程获得钥匙，执行下面内容
         cout<<"this is father!\n"<<endl;
         sleep(2);
         backkey(semid);//放回钥匙
    }
    cout<<"子进程退出!信号量共享资源销毁!"<<endl;
    semctl(semid,0,IPC_RMID);//销毁信号量
}